//Author:       Miguel Dominguez & Heath Cazeau
//Date:         3/9/2011
//Class:        Software Engineering
//Project:      Jaz Interpreter
//File:         Lexer.cpp

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
#include "Lexer.h"

Instruction Lexer::ToInstructions(ifstream & input)
{
    char cTemp[256];
    input.getline(cTemp, 256);
    string temp (cTemp, strlen(cTemp));
    int returnLoc = temp.find("\r");
    if(returnLoc >= 0)
    {
        temp.replace(returnLoc,returnLoc,"");
    }

    Instruction first = *Lexer::ToInstruction(temp);
    
    Instruction * current = &first;
    while(!input.eof())
    {
        input.getline(cTemp, 256);
        string temp (cTemp, strlen(cTemp));
        int returnLoc = temp.find("\r");
        if(returnLoc >= 0)
        {
            temp.replace(returnLoc,1,"");
        }

        //Prevent blank lines from being converted into Instruction objects
        if(temp.length() > 0)
        {
            (*current).setNextInstruction(Lexer::ToInstruction(temp));
            current = (*current).getNextInstruction();
        }
    }
    return first;
}

Instruction * Lexer::ToInstruction(string input)
{
    int keywordBegin = 0;
    keywordBegin = input.find_first_not_of(" \t\f\n\r",0);
    int keywordEnd = input.find_first_of(" \t", keywordBegin);
    string keyword = input.substr(keywordBegin,keywordEnd - keywordBegin);
    string argument;

    int argumentBegin = input.find_first_not_of(" \t", keywordEnd);
    int argumentEnd = input.find_last_not_of(" \t\f\n\r");

    if(argumentBegin > -1 && argumentEnd > -1)
    {
        
        argument = input.substr(argumentBegin, argumentEnd - argumentBegin + 1);
    }

    else
    {
        argument = "";
    }

    Instruction * output = new Instruction(keyword, argument);
    return output;
}

map<string, Instruction *> Lexer::GetLabelLocations(Instruction input)
{
    map<string, Instruction *> output;
    Instruction * current = &input;

    while((*current).getNextInstruction() != NULL)
    {
        if((*current).getKeyword().compare("label") == 0)
        {
            output.insert(pair<string, Instruction *>((*current).getArgument(),(*current).getNextInstruction()));
        }
        current = (*current).getNextInstruction();
    }

    if((*current).getKeyword().compare("label") == 0)
    {
        output.insert(pair<string, Instruction *>((*current).getArgument(),(*current).getNextInstruction()));
    }

    return output;
}

void Lexer::StripLabelsFromCode(Instruction & input, map<string, Instruction *> labelLocs)
{
    if(input.getKeyword().compare("label") == 0)
    {
        input = *(input.getNextInstruction());
    }

    Instruction * current = &input;
    Instruction * previous = NULL;
    string currentInst = input.getKeyword();

    while((*current).getNextInstruction() != NULL)
    {
        if((*current).getKeyword().compare("label") == 0)
        {
            (*previous).setNextInstruction((*current).getNextInstruction());
            current = (*current).getNextInstruction();
        }
        else
        {
            previous = current;
            current = (*current).getNextInstruction();
        }
        currentInst = (*current).getKeyword();
    }

    if((*current).getKeyword().compare("label") == 0)
    {
        (*previous).setNextInstruction(NULL);
    }
}
